/*
 * Copyright (c) 2018 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <stdio.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(sensor, CONFIG_BT_LOG_LEVEL);

#if defined(CONFIG_GPIO)
#include <zephyr/drivers/gpio.h>

/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS   1000

/* The devicetree node identifier for the "led0" alias. */
#define LED1_NODE DT_ALIAS(led1)

/*
 * A build error on this line means your board is unsupported.
 * See the sample documentation for information on how to fix this.
 */
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED1_NODE, gpios);
#endif

#ifdef CONFIG_LIS3MDL_TRIGGER
static int lis3mdl_trig_cnt;

static void lis3mdl_trigger_handler(const struct device *dev,
				    const struct sensor_trigger *trig)
{
	sensor_sample_fetch_chan(dev, trig->chan);
	lis3mdl_trig_cnt++;
}
#endif

/**
 * @description:
 * @return {*}
 */
static void thread_sensor_entry(void)
{
	struct sensor_value temp, hum, press;
	struct sensor_value magn_xyz[3], accel_xyz[3];
	const struct device *const hts221 = DEVICE_DT_GET_ONE(st_hts221);
	const struct device *const lis3mdl = DEVICE_DT_GET_ONE(st_lis3mdl_magn);
	const struct device *const lsm6ds0 = DEVICE_DT_GET_ONE(st_lsm6ds0);
	const struct device *const lps25hb = DEVICE_DT_GET_ONE(st_lps25hb_press);
#if defined(CONFIG_LIS3MDL_TRIGGER)
	struct sensor_trigger trig;
	int cnt = 1;
#endif

	if (!device_is_ready(hts221)) {
		LOG_INF("%s: device not ready.\n", hts221->name);
		return;
	}
	if (!device_is_ready(lis3mdl)) {
		LOG_INF("%s: device not ready.\n", lis3mdl->name);
		return;
	}
	if (!device_is_ready(lsm6ds0)) {
		LOG_INF("%s: device not ready.\n", lsm6ds0->name);
		return;
	}
	if (!device_is_ready(lps25hb)) {
		LOG_INF("%s: device not ready.\n", lps25hb->name);
		return;
	}

#ifdef CONFIG_LIS3MDL_TRIGGER
	trig.type = SENSOR_TRIG_DATA_READY;
	trig.chan = SENSOR_CHAN_MAGN_XYZ;
	sensor_trigger_set(lis3mdl, &trig, lis3mdl_trigger_handler);
#endif

#if defined(CONFIG_GPIO)
    int ret;

	if (!device_is_ready(led.port)) {
		return;
	}

	ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}
#endif

	while (1) {

		/* Get sensor samples */

		if (sensor_sample_fetch(hts221) < 0) {
			LOG_INF("HTS221 Sensor sample update error\n");
			return;
		}
		if (sensor_sample_fetch(lps25hb) < 0) {
			LOG_INF("LPS25HB Sensor sample update error\n");
			return;
		}
#ifndef CONFIG_LIS3MDL_TRIGGER
		if (sensor_sample_fetch(lis3mdl) < 0) {
			LOG_INF("LIS3MDL Sensor sample update error\n");
			return;
		}
#endif
		if (sensor_sample_fetch(lsm6ds0) < 0) {
			LOG_INF("LSM6DS0 Sensor sample update error\n");
			return;
		}

		/* Get sensor data */

		sensor_channel_get(hts221, SENSOR_CHAN_AMBIENT_TEMP, &temp);
		sensor_channel_get(hts221, SENSOR_CHAN_HUMIDITY, &hum);
		sensor_channel_get(lps25hb, SENSOR_CHAN_PRESS, &press);
		sensor_channel_get(lis3mdl, SENSOR_CHAN_MAGN_XYZ, magn_xyz);
		sensor_channel_get(lsm6ds0, SENSOR_CHAN_ACCEL_XYZ, accel_xyz);

		/* Display sensor data */
		LOG_INF("X-NUCLEO-IKS01A1 sensor dashboard\n\n");

		/* temperature */
		LOG_INF("HTS221: Temperature: %.1f C\n",
		       sensor_value_to_double(&temp));

		/* humidity */
		LOG_INF("HTS221: Relative Humidity: %.1f%%\n",
		       sensor_value_to_double(&hum));

		/* pressure */
		LOG_INF("LPS25HB: Pressure:%.1f kpa\n",
		       sensor_value_to_double(&press));

		/* magneto data */
		LOG_INF(
		 "LIS3MDL: Magnetic field (gauss): x: %.1f, y: %.1f, z: %.1f\n",
		 sensor_value_to_double(&magn_xyz[0]),
		 sensor_value_to_double(&magn_xyz[1]),
		 sensor_value_to_double(&magn_xyz[2]));

		/* acceleration */
		LOG_INF(
		   "LSM6DS0: Acceleration (m.s-2): x: %.1f, y: %.1f, z: %.1f\n",
		   sensor_value_to_double(&accel_xyz[0]),
		   sensor_value_to_double(&accel_xyz[1]),
		   sensor_value_to_double(&accel_xyz[2]));


#if defined(CONFIG_LIS3MDL_TRIGGER)
		LOG_INF("%d:: lis3mdl trig %d\n", cnt, lis3mdl_trig_cnt);
		cnt++;
#endif

		k_sleep(K_MSEC(2000));

		#if defined(CONFIG_GPIO)
        ret = gpio_pin_toggle_dt(&led);
		if (ret < 0) {
			return;
		}
#endif
	}
}

static K_KERNEL_STACK_DEFINE(sensor_manager_stack, 1024);
static struct k_thread sensor_manager_thread_data;
static void thread_sensor_entry(void);

/**
 * @description:
 * @return {*}
 */
void sensor_manager_init(void)
{
	const k_tid_t tid =
	k_thread_create(&sensor_manager_thread_data, sensor_manager_stack,
			K_KERNEL_STACK_SIZEOF(sensor_manager_stack),
			(k_thread_entry_t)thread_sensor_entry, NULL, NULL, NULL,
			K_PRIO_COOP(6),
			0, K_NO_WAIT);
	k_thread_name_set(tid, "sensor_manager");
}